package com.geek.novel.utils;

import com.geek.novel.bo.AppContext;

import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import io.reactivex.Observer;
import okhttp3.*;
import org.jetbrains.annotations.NotNull;

/**
 * 网络请求工具
 * @author Hydra
 */
public class HttpUtils {
	
	// 编码格式。发送编码格式统一用UTF-8
	private static final String ENCODING = "UTF-8";
	
	// 设置读取超时时间，单位毫秒。
	private static final int READ_TIMEOUT = 6000;

	// 设置写入超时时间，单位毫秒。
	private static final int WRITE_TIMEOUT = 6000;

	// 设置调用超时时间，单位毫秒。
	private static final int CALL_TIMEOUT = 6000;

	// 设置连接超时时间，单位毫秒。
	private static final int CONNECT_TIMEOUT = 6000;


	/**
	 * 解析url，其实也就是拼上斜杆
	 */
	public static String parseUrl(String baseUrl, String path){
		if(path.startsWith("http://") || path.startsWith("https://")){
			return path;
		}
		if(!baseUrl.endsWith("/")){
			baseUrl = baseUrl + "/";
		}

		if(path.startsWith("/")){
			path = path.substring(1);
		}
		return baseUrl + path;
	}


	public static HttpClientResult doGet(String url){
		//拆分URL
		Map<String, String> headers = new HashMap<>();
		try {
			headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36");
			headers.put("Accept", "*/*");
			URI uri = new URI(url);
			String host = uri.getHost();
			headers.put("Host", host);
			headers.put("Referer", host);
			headers.put("Accept-Encoding", "identity");
			headers.put("Connection", "keep-alive");
			headers.put("Content-Type", "text/html; charset=utf-8");
		} catch (URISyntaxException e) {
			LogCatUtil.INSTANCE.e("???", e.getMessage(), e);
		}
		return doGet(url, headers, null);
	}

	public static HttpClientResult doGet(String url, Map<String, String> headers, Map<String, String> params){
		HttpClientResult result = new HttpClientResult();

		if(url.endsWith(".html/")){
			url = url.substring(0, url.length()-1);
		}

		try {
			//构建请求对象
			Request request = buildRequest(url, headers, params);

			//构建请求客户端
			OkHttpClient client = buildClient();
			Response response = client.newCall(request).execute();
			ResponseBody body = response.body();
			assert body != null;

			StringBuilder content = new StringBuilder();
			if("octet-stream".equals(Objects.requireNonNull(body.contentType()).subtype())){
				Reader reader = body.charStream();
				BufferedReader br = new BufferedReader(reader);
				String line;
				while((line = br.readLine()) != null){
					content.append(line);
				}
			}else{
				content.append(body.string());
			}

			result.setCode(response.code());
			result.setContent(content.toString());
			result.setMessage("请求成功");

		} catch (Exception e) {
			LogCatUtil.INSTANCE.e("???", "请求地址："+url, e);
			LogCatUtil.INSTANCE.e("???", e.getMessage(), e);
			result.setCode(HttpClientResult.RESPONSE_CODE_ERROR);
			result.setMessage(e.getMessage());
			result.setException(e);
		}
		return result;
	}

	public static Observable<HttpClientResult> doGetAsync(String url) {
		return doGetAsync(url, null, null);
	}
	public static Observable<HttpClientResult> doGetAsync(String url, Map<String, String> headers, Map<String, String> params) {
		MyObserver<HttpClientResult> observable = new MyObserver<>();

		//构建请求客户端
		OkHttpClient client = buildClient();

		//构建请求对象
		Request request = buildRequest(url, headers, params);

		client.newCall(request).enqueue(new Callback() {
			@Override
			public void onFailure(@NotNull Call call, @NotNull IOException e) {
				observable.onComplete();
				observable.onError(e);
			}
			@Override
			public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
				observable.onComplete();
				if(response.isSuccessful()){//回调的方法执行在子线程。
					assert response.body() != null;
					String content = response.body().string();
					HttpClientResult result = new HttpClientResult(response.code(), content);
					result.setMessage("请求成功");
					observable.onNext(result);
				}
			}
		});
		return observable;
	}


	/**构建请求对象*/
	static Request buildRequest(String url, Map<String, String> headers, Map<String, String> params){
		Request.Builder builder = new Request.Builder()
				.url(url)
//				.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=gb2312")
//				.addHeader("User-Agent", "Mozilla/5.0 (compatible; Googlebot/2.1; +https://www.google.com/bot.html)")
				;
		if (headers != null) {
			Set<Map.Entry<String, String>> entrySet = headers.entrySet();
			for (Map.Entry<String, String> entry : entrySet) {
				// 设置到请求头到HttpRequestBase对象中
				builder.addHeader(entry.getKey(), entry.getValue());
			}
		}
		return builder.build();
	}

	/**构建请求客户端*/
	static OkHttpClient buildClient(){
		return new OkHttpClient.Builder()
				.callTimeout(CALL_TIMEOUT, TimeUnit.MILLISECONDS)
				.connectTimeout(CONNECT_TIMEOUT, TimeUnit.MILLISECONDS)
				.writeTimeout(WRITE_TIMEOUT, TimeUnit.MILLISECONDS)
				.readTimeout(READ_TIMEOUT, TimeUnit.MILLISECONDS)
				.protocols(Collections.singletonList(Protocol.HTTP_1_1))
				.retryOnConnectionFailure(true)
				.build();
	}
	

	static class MyObserver<T> extends Observable<T>{
		
		Observer<? super T> observer = null;
		
		@Override
		protected void subscribeActual(Observer<? super T> observer) {
			this.observer = observer;
		}
		
		public Observer<? super T> getObserver() {
			return observer;
		}
		
		public void onComplete(){
			if(observer != null){
				//在主线程运行
				doOnMainThread(() -> observer.onComplete());
			}
		}
		
		public void onNext(T t){
			if(observer != null){
				doOnMainThread(() -> observer.onNext(t));
			}
		}
		
		public void onError(Exception e){
			if(observer != null){
				doOnMainThread(() -> observer.onError(e));
			}
		}
		
		private void doOnMainThread(Runnable r){
			AppContext.Companion.getContext().doOnMainThread(r);
		}
	}
	
}
